package zsxking.batchfilerenamer;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * BatchFileRenamer renames a set of target files, according to file names of a set of 
 * source files.
 * 
 * @author Shaoxuan Zhang
 *
 */
public class BatchFileRenamer {
  
  private boolean excludeExtension = true;
  
  private String DOT = ".";
  
  /**
   * Rename source files accoding to the names of target files.
   * Files are matched with the order in the list.
   * @param sourceFiles source files list.
   * @param targetFiles target files list.
   * @return List of rename result of each file. True if succeed, false otherwise.
   * @throws FileNameMatchException If errors occur.
   */
  public List<Boolean> rename(List<File> sourceFiles, List<File> targetFiles) 
    throws FileNameMatchException {
    if (targetFiles == null || sourceFiles == null) {
      throw new FileNameMatchException("Target files and source files cannot be null.");
    }
    if (targetFiles.size() != sourceFiles.size()) {
      throw new FileNameMatchException("Numbers of target files and source files do not match.");
    }
    List<Boolean> results = new ArrayList<Boolean> ();
    for (int i = 0; i < sourceFiles.size(); i++) {
      boolean targetHasExt = true;
      boolean sourceHasExt = true;
      // find ext of target file.
      String destFileName = targetFiles.get(i).getName();
      int destExtIndex = destFileName.lastIndexOf(DOT);
      if (destExtIndex == -1) {
        destExtIndex = destFileName.length();
        sourceHasExt = false;
      }
      // find ext of source file.
      String srcName = sourceFiles.get(i).getName();
      int sourceExtIndex = srcName.lastIndexOf(DOT);
      if (sourceExtIndex == -1) {
        sourceExtIndex = srcName.length();
        targetHasExt = false;
      }
      if (!targetHasExt && !sourceHasExt) {
        throw new FileNameMatchException(
            "Cannot match file name because both target and source file lack of ext.");
      }
      // exclude target ext.
      if (excludeExtension) {
        destFileName = destFileName.substring(0, destExtIndex);
      }
      // add source ext to target name finish dest file.
      String sourceExt = sourceFiles.get(i).getName().substring(sourceExtIndex);
      File destFile = new File(sourceFiles.get(i).getParent() + File.separatorChar + destFileName + sourceExt);
      boolean result = sourceFiles.get(i).renameTo(destFile);
      if (result) {
        sourceFiles.set(i, destFile);
      }
      results.add(result);
    }
    return results;
    
  }

  /**
   * Rename source files accoding to the names of target files.
   * Files are matched with alphabetical order in the list.
   * targetFiles and sourceFiles will be sorted when return.
   * @param sourceFiles source files list.
   * @param targetFiles target files list.
   * @return List of rename result of each file. True if succeed, false otherwise.
   * @throws FileNameMatchException If errors occur.
   */
  public List<Boolean> renameByAlphabeticalOrder(List<File> sourceFiles, List<File> targetFiles) 
    throws FileNameMatchException {
    Collections.sort(targetFiles);
    Collections.sort(sourceFiles);
    return rename(sourceFiles, targetFiles);
  }
  
  /**
   * @param excludeExtension the excludeExtension to set
   */
  public void setExcludeExtension(boolean excludeExtension) {
    this.excludeExtension = excludeExtension;
  }

  /**
   * @return the excludeExtension
   */
  public boolean isExcludeExtension() {
    return excludeExtension;
  }
}
